<?php

namespace Forxx\Api;

use Exception;

trait ArrayListDataFilter
{
    public static function compareEQ($item, $condition)
    {
        if (count($condition) < 1) {
            return false;
        }
        $compare = array_shift($condition);
        return $item == $compare;
    }

    public static function compareNEQ($item, $condition)
    {
        if (count($condition) < 1) {
            return false;
        }
        $compare = array_shift($condition);
        return $item != $compare;
    }

    public static function compareLT($item, $condition)
    {
        if (count($condition) < 1) {
            return false;
        }
        $compare = array_shift($condition);
        return intval($item) < intval($compare);
    }

    public static function compareLTE($item, $condition)
    {
        if (count($condition) < 1) {
            return false;
        }
        $compare = array_shift($condition);
        return intval($item) <= intval($compare);
    }

    public static function compareGT($item, $condition)
    {
        if (count($condition) < 1) {
            return false;
        }
        $compare = array_shift($condition);
        return intval($item) > intval($compare);
    }

    public static function compareGTE($item, $condition)
    {
        if (count($condition) < 1) {
            return false;
        }
        $compare = array_shift($condition);
        return intval($item) >= intval($compare);
    }

    public static function compareBETWEEN($item, $condition)
    {
        if (count($condition) != 2) {
            return false;
        }

        return intval($item) >= intval($condition[0]) && intval($item) <= intval($condition[1]);
    }

    public static function compareIN($item, $condition)
    {  
        if (count($condition) < 1) {
            return false;
        }
        return in_array($item, $condition[0]);
    }

    public static function compareNOTIN($item, $condition)
    {
        if (count($condition) < 1) {
            return false;
        }
        return !in_array($item, $condition[0]);
    }

    public static function formatOP($op){
        $op = strtoupper($op);
        if($op == '<'){
            $op = 'LT';
        }
        else if($op == '<='){
            $op = 'LTE';
        }
        else if($op == '>'){
            $op = 'GT';
        }
        else if($op == '>='){
            $op = 'GTE';
        }
        else if($op == '=' || $op == '=='){
            $op = 'EQ';
        }
        else if($op == '!=' || $op == '<>'){
            $op = 'NEQ';
        }
        return $op;
    }

    protected static function doFilter($item,$condition){
        foreach ($condition as $key => $cond) {
            if (!isset($item[$key])) {
                return false;
            }
            $value = $item[$key];
            if (!is_array($cond)) {              
                if(strcasecmp($value,$cond) !== 0){  //数据库中的数据  不区分大小写                   
                    return false;
                }
            } else {
                if (count($cond) < 1) {
                    return false;
                }
                $op = self::formatOP(array_shift($cond));
                $compareRet = false;
                if ($op != 'FN') {
                    $method = 'compare' . $op;
                    if (method_exists(static::class, $method)) {
                        $compareRet = call_user_func(['self', $method], $value, $cond);
                    } else {
                        throw new Exception('unkonwn filter op ' . $op . ' in filter ' . json_encode($condition));                 
                    }
                } else {
                    if (count($cond) < 1) {
                        throw new Exception('op ' . $op . ' net set funcName ' . json_encode($condition));
                    }
                    $fnName = array_shift($cond);                 
                    $compareRet = call_user_func($fnName, $item);
                }
                if ($compareRet == false) {
                    return false;
                }
            }
        }
        return true;
    }

    public static function filterOne($data, $condition)
    {
        if (count($data) < 1) {
            return [];
        }
        if (count($condition) < 1) {
            return $data;
        }
        foreach($data as $d){
            $ret = self::doFilter($d,$condition);
            if($ret){
                return $d;
            }
        }
        return [];
    }

    public static function filter($data, $condition)
    {
        if (count($data) < 1) {
            return [];
        }
        if (count($condition) < 1) {
            return $data;
        }
        $data = array_filter($data, function ($item) use ($condition) {
            return self::doFilter($item, $condition);
        });
        return array_values($data);
    }

    public static function sort($data, $sort)
    {
        if (count($data) < 2 || count($sort) < 1) {
            return $data;
        }
        if (!is_array($sort[0])) { //使用时$sort 需要为 二维数组
            $sort = [$sort];
        }
        $firstItem = $data[0];
        $key = 0;
        $args = [];
        foreach ($sort as $sortInfo) {
            $field = $sortInfo[0];
            $sortOrder = (isset($sortInfo[1]) && strtoupper($sortInfo[1]) == 'DESC') ? SORT_DESC : SORT_ASC;
            $sortFlag = is_numeric($firstItem[$field]) ? SORT_NUMERIC : SORT_REGULAR;
            $args[$key] = array_column($data, $field);
            $args[$key + 1] = $sortOrder;
            $args[$key + 2] = $sortFlag;
            $key += 3;
        }
        //此处必须为引用才能使数据生效
        $args[] = &$data;

        call_user_func_array('array_multisort', $args);

        return $data;
    }
}
